স্প্রিং সিকিউরিটি প্রোজেক্টে Unit এবং Integration Testing খুবই গুরুত্বপূর্ণ। সঠিকভাবে সিকিউরিটি কনফিগারেশন এবং অথেন্টিকেশন-অথরাইজেশন ফিচারগুলো পরীক্ষা না করলে, অ্যাপ্লিকেশনের সিকিউরিটি ঝুঁকির মুখে পড়তে পারে। এই টেস্টিং পদ্ধতিগুলোর মাধ্যমে আমরা নিশ্চিত করতে পারি যে সিকিউরিটি কনফিগারেশন সঠিকভাবে কাজ করছে।
এখানে আমরা আলোচনা করব কিভাবে Unit Testing এবং Integration Testing স্প্রিং সিকিউরিটির জন্য করা যায়।
১. Unit Testing for Spring Security
Unit Testing মূলত সুনির্দিষ্ট একটি মেথড বা ক্লাসের লজিক পরীক্ষার জন্য ব্যবহৃত হয়। স্প্রিং সিকিউরিটি ব্যবহার করার সময়, আমরা সাধারনত AuthenticationManager, UserDetailsService, এবং SecurityContext টেস্ট করি।
উদাহরণ: UserDetailsService এর ইউনিট টেস্ট
@RunWith(MockitoJUnitRunner.class)
public class UserDetailsServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private CustomUserDetailsService userDetailsService;
@Test
public void testLoadUserByUsername() {
// Mocking database return value
User mockUser = new User("user", "{noop}password", Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")));
when(userRepository.findByUsername("user")).thenReturn(Optional.of(mockUser));
// Test the UserDetailsService method
UserDetails userDetails = userDetailsService.loadUserByUsername("user");
// Assertions
assertEquals("user", userDetails.getUsername());
assertEquals("{noop}password", userDetails.getPassword());
assertTrue(userDetails.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("ROLE_USER")));
}
}
এখানে CustomUserDetailsService ক্লাসে loadUserByUsername() মেথডটিকে ইউনিট টেস্ট করা হচ্ছে। আমরা মক করা ডাটাবেস থেকে একটি ইউজার অবজেক্ট ফেরত দিয়ে তার তথ্য যাচাই করেছি।
২. Integration Testing for Spring Security
Integration Testing হলো পুরো অ্যাপ্লিকেশনের অংশগুলোর (যেমন, ডাটাবেস, সার্ভিসেস, কন্ট্রোলার ইত্যাদি) মধ্যে ইন্টারঅ্যাকশন পরীক্ষা করা। স্প্রিং সিকিউরিটি কনফিগারেশন সহ ইন্টিগ্রেশন টেস্টিং করা খুবই গুরুত্বপূর্ণ, কারণ এতে সিকিউরিটি ফিল্টার, অথেন্টিকেশন, অথরাইজেশন এবং অন্যান্য সিকিউরিটি ফিচারগুলো পরীক্ষা করা যায়।
উদাহরণ: Integration Test for Secured Endpoint
ধরা যাক, আমাদের একটি সিকিউরড GET /user/{id} এন্ডপয়েন্ট রয়েছে, যেখানে কেবলমাত্র অথেন্টিকেটেড ব্যবহারকারীরা অ্যাক্সেস পেতে পারেন। এখানে আমরা এই এন্ডপয়েন্টের ইন্টিগ্রেশন টেস্টিং করব।
@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerIntegrationTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserRepository userRepository;
@Test
public void testGetUserByIdWithValidUser() throws Exception {
User mockUser = new User("user", "{noop}password", Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")));
when(userRepository.findById(1L)).thenReturn(Optional.of(mockUser));
mockMvc.perform(get("/user/1")
.with(user("user").password("{noop}password").roles("USER")))
.andExpect(status().isOk())
.andExpect(jsonPath("$.username").value("user"));
}
@Test
public void testGetUserByIdWithInvalidUser() throws Exception {
mockMvc.perform(get("/user/1")
.with(user("user").password("{noop}password").roles("USER")))
.andExpect(status().isUnauthorized());
}
}
এখানে, MockMvc ব্যবহার করে আমরা HTTP রিকোয়েস্ট পাঠাচ্ছি এবং সিকিউরড এন্ডপয়েন্টটি পরীক্ষা করছি।
/user/1এন্ডপয়েন্টটি শুধুমাত্র অথেন্টিকেটেড ইউজারদের জন্যই অ্যাক্সেসযোগ্য।- প্রথম টেস্টে, একটি বৈধ ব্যবহারকারী (যার ইউজারনেম "user" এবং পাসওয়ার্ড
{noop}password) রিকোয়েস্ট পাঠালে 200 OK স্ট্যাটাস কোড এবং ইউজারের তথ্য রিটার্ন হবে। - দ্বিতীয় টেস্টে, যদি ব্যবহারকারী অননুমোদিত হয়, তবে 401 Unauthorized রিটার্ন হবে।
৩. Remember-Me Authentication এর Integration Test
আমরা যদি Remember-Me Authentication কনফিগার করি, তাহলে এটি টেস্ট করার জন্য একটি ইন্টিগ্রেশন টেস্টের উদাহরণ দেখানো হলো:
@SpringBootTest
@AutoConfigureMockMvc
public class RememberMeIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testRememberMeFunctionality() throws Exception {
mockMvc.perform(formLogin("/login").user("user").password("{noop}password").param("remember-me", "true"))
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrl("/home"));
// Now, send another request after some time to check remember-me functionality
mockMvc.perform(get("/home"))
.andExpect(status().isOk())
.andExpect(content().string(containsString("Welcome, user")));
}
}
এখানে, প্রথমে একটি Remember-Me ফর্ম লগইন করা হয়েছে এবং দ্বিতীয় রিকোয়েস্টে ইউজারকে আবার লগইন না করেই হোম পেজে প্রবেশ করতে দেওয়া হয়েছে।
৪. Testing Security Context
স্প্রিং সিকিউরিটির SecurityContext টেস্ট করা অত্যন্ত গুরুত্বপূর্ণ, কারণ এটি ইউজারের অথেন্টিকেশন এবং অথরাইজেশন তথ্য ধারণ করে।
@Test
public void testSecurityContext() {
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
assertNotNull(authentication);
assertEquals("user", authentication.getName());
assertTrue(authentication.getAuthorities().stream()
.anyMatch(authority -> authority.getAuthority().equals("ROLE_USER")));
}
এই টেস্টটি নিশ্চিত করবে যে SecurityContext সঠিকভাবে ইউজারের তথ্য ধারণ করছে এবং এটি যথাযথভাবে অথরিটি যাচাই করছে।
উপসংহার:
- Unit Testing-এ সাধারণত মেথড বা সেবা স্তরের সিকিউরিটি পরীক্ষা করা হয়, যেমন UserDetailsService, AuthenticationManager, এবং SecurityContext।
- Integration Testing-এ স্প্রিং সিকিউরিটি কনফিগারেশন, অথেন্টিকেশন, অথরাইজেশন এবং সিকিউরিটি ফিল্টার সিস্টেমের কার্যকারিতা পরীক্ষা করা হয়।
- স্প্রিং সিকিউরিটি অ্যানোটেশন (যেমন
@WithMockUser) এবং MockMvc ব্যবহার করে সহজেই ইন্টিগ্রেশন টেস্ট করা যায়।
Read more